/*

 * Copyright (C) 2021 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */
package org.aviran.cookiebar2;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Text;
import ohos.agp.components.Button;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

/**
 * CookieBottomView
 *
 * @since : 2021.5.24
 */
public class CookieBottomView extends ComponentContainer {
    private static final int EVENT_MESSAGE_GREEN = 1;

    /**
     * 自定义的component
     */
    public Component myComponent;
    /**
     * myHandler
     */
    public MyEventHandler myHandler;
    /**
     * 屏幕的X轴距离
     */
    public int screenX;
    /**
     * 屏幕Y轴距离
     */
    public int screenY;
    /**
     * myHeight
     */
    public int myHeight;

    /**
     * 下拉栏是否存在
     */
    public Boolean isExit = false;

    /**
     * 是否需要Top栏上去了在下来
     */
    public Boolean isNeedTopToBottom = true;

    /**
     * 当前是不是一个不需要缩回的cookieBar
     */
    public Boolean bool = false;
    /**
     * 持续时间
     */
    private int duration = 5000;


    private CookieBottomView cookieBottomComponent; // 显示时的CookieBottomView
    private InnerEvent event;
    private EventRunner runner;
    private AnimatorProperty settingAnimatorProperty;
    private DirectionalLayout directionalLayout;
    private final Context myContext;
    private ShapeElement element;
    private AnimatorValue mAnimator;

    private Text title;
    private Text message;
    private Text displayText;
    private Text action;
    private Text blank_1;
    private Text blank_2;
    private Text blank_3;
    private Text blank_4;
    private Text blank_5;
    private Image image;
    private Button NewBt;
    private Button openBt;
    private Button saveBt;
    private Color titleColor;
    private Color messageColor;
    private Color actionColor;
    private String titleStr;
    private String messageStr;
    private String actionStr;
    private Integer iconID;

    /**
     * CookieBottomView构造器
     *
     * @param context context
     * @param attrSet 属性
     */
    public CookieBottomView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        myContext = context;
        myComponent = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_cookie_bottom_layout, null, false);
        initComponent();
        myComponent.setVisibility(Component.HIDE);
        myComponent.setClickedListener(component -> {
            // 设置一个监听事件，避免点击穿透触发component下面的button点击事件
        });
        addComponent(myComponent);
        titleStr = getString(attrSet, "title", "");
        messageStr = getString(attrSet, "message", "");
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                myHeight = 600;
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {
            }
        });
        screenY = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes().height;
        screenX = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes().width;
        myComponent.setTranslationY(screenY);
        mAnimator = new AnimatorValue();
    }

    /**
     * initComponent
     */
    private void initComponent() {
        if (myComponent.findComponentById(ResourceTable.Id_myLayout) instanceof DirectionalLayout) {
            directionalLayout = (DirectionalLayout) myComponent.findComponentById(ResourceTable.Id_myLayout);
        }
        if (myComponent.findComponentById(ResourceTable.Id_title) instanceof Text) {
            title = (Text) myComponent.findComponentById(ResourceTable.Id_title);
        }
        if (myComponent.findComponentById(ResourceTable.Id_message) instanceof Text) {
            message = (Text) myComponent.findComponentById(ResourceTable.Id_message);
        }
        if (myComponent.findComponentById(ResourceTable.Id_action) instanceof Text) {
            action = (Text) myComponent.findComponentById(ResourceTable.Id_action);
        }
        if (myComponent.findComponentById(ResourceTable.Id_img) instanceof Image) {
            image = (Image) myComponent.findComponentById(ResourceTable.Id_img);
        }
        if (myComponent.findComponentById(ResourceTable.Id_New) instanceof Button) {
            NewBt = (Button) myComponent.findComponentById(ResourceTable.Id_New);
        }
        NewBt.setClickedListener(component -> NewBt.setText("CLICKED!"));
        if (myComponent.findComponentById(ResourceTable.Id_open) instanceof Button) {
            openBt = (Button) myComponent.findComponentById(ResourceTable.Id_open);
        }
        openBt.setClickedListener(component -> openBt.setText("CLICKED!"));
        if (myComponent.findComponentById(ResourceTable.Id_save) instanceof Button) {
            saveBt = (Button) myComponent.findComponentById(ResourceTable.Id_save);
        }
        saveBt.setClickedListener(component -> saveBt.setText("CLICKED!"));
        if (myComponent.findComponentById(ResourceTable.Id_blank_1) instanceof Text) {
            blank_1 = (Text) myComponent.findComponentById(ResourceTable.Id_blank_1);
        }
        if (myComponent.findComponentById(ResourceTable.Id_blank_2) instanceof Text) {
            blank_2 = (Text) myComponent.findComponentById(ResourceTable.Id_blank_2);
        }
        if (myComponent.findComponentById(ResourceTable.Id_blank_3) instanceof Text) {
            blank_3 = (Text) myComponent.findComponentById(ResourceTable.Id_blank_3);
        }
        if (myComponent.findComponentById(ResourceTable.Id_blank_4) instanceof Text) {
            blank_4 = (Text) myComponent.findComponentById(ResourceTable.Id_blank_4);
        }
        if (myComponent.findComponentById(ResourceTable.Id_blank_5) instanceof Text) {
            blank_5 = (Text) myComponent.findComponentById(ResourceTable.Id_blank_5);
        }
    }

    /**
     * setCookieBottomView
     *
     * @param component component
     */
    public void setCookieBottomView(CookieBottomView component) {
        this.cookieBottomComponent = component;
    }

    /**
     * 设置标题
     *
     * @param titleStr 标题信息
     */
    public void setTitle(String titleStr) {
        this.titleStr = titleStr;
    }

    /**
     * 设置标题颜色
     *
     * @param color 颜色
     */
    public void setTitleColor(Color color) {
        this.titleColor = color;
    }

    /**
     * 设置信息
     *
     * @param messageStr messageStr
     */
    public void setMessage(String messageStr) {
        this.messageStr = messageStr;
    }

    /**
     * 设置信息颜色
     *
     * @param color 颜色
     */
    public void setMessageColor(Color color) {
        this.messageColor = color;
    }

    /**
     * 设置Action的String
     *
     * @param actionStr actionStr
     */
    public void setAction(String actionStr) {
        this.actionStr = actionStr;
    }

    /**
     * 设置Action颜色
     *
     * @param color 颜色
     */
    public void setActionColor(Color color) {
        this.actionColor = color;
    }

    /**
     * 设置Icon
     *
     * @param iconID icon
     */
    public void setIcon(Integer iconID) {
        this.iconID = iconID;
    }

    /**
     * 设置动画持续时间
     *
     * @param duration 时间ms
     */
    public void setDuration(Integer duration) {
        this.duration = duration;
    }

    /**
     * 设置背景颜色
     *
     * @param element 背景颜色
     */
    public void setBackgroundColor(ShapeElement element) {
        this.element = element;
    }

    /**
     * 是否显示三个Button
     *
     * @param bool bool
     */
    public void showThreeStatusButton(Boolean bool) {
        this.bool = bool;
    }

    /**
     * 设置显示的文字
     *
     * @param displayText displayText
     */
    public void setDisplayText(Text displayText) {
        this.displayText = displayText;
    }

    /**
     * 设置NEW按钮的监听
     *
     * @param clickedListener clickedListener
     */
    public void setNewBtListener(ClickedListener clickedListener) {
        NewBt.setVisibility(Component.VISIBLE);
        NewBt.setClickedListener(clickedListener);
    }

    /**
     * 设置Open按钮的监听
     *
     * @param clickedListener clickedListener
     */
    public void setOpenBtListener(ClickedListener clickedListener) {
        openBt.setVisibility(Component.VISIBLE);
        openBt.setClickedListener(clickedListener);
    }

    /**
     * 设置Save的监听
     *
     * @param clickedListener clickedListener
     */
    public void setSaveBtListener(ClickedListener clickedListener) {
        saveBt.setVisibility(Component.VISIBLE);
        saveBt.setClickedListener(clickedListener);
    }

    private void setStyle() {
        boolStatus();
        myComponent.setBackground(element);
        title.setText(titleStr);
        message.setText(messageStr);
        if (titleColor != null) {
            title.setTextColor(titleColor);
        }
        if (messageColor != null) {
            message.setTextColor(messageColor);
        }
        if (actionColor != null) {
            action.setTextColor(actionColor);
        }
        if (iconID != null) {
            image.setPixelMap(iconID);
        }
        if (actionStr != null) {
            action.setVisibility(Component.VISIBLE);
            action.setText(actionStr);
        }
        if ("CLOSE".equals(action.getText())) {
            action.setClickedListener(component -> {
                isNeedTopToBottom = false;
                startAnimationBottom();
            });
        } else {
            action.setClickedListener(component -> displayText.setText("Action engaged!"));
        }
    }

    private void boolStatus () {
        if (bool) {
            blank_1.setVisibility(Component.VISIBLE);
            blank_2.setVisibility(Component.VISIBLE);
            blank_3.setVisibility(Component.VISIBLE);
            blank_4.setVisibility(Component.VISIBLE);
            blank_5.setVisibility(Component.VISIBLE);
            NewBt.setVisibility(Component.VISIBLE);
            NewBt.setText("NEW");
            openBt.setVisibility(Component.VISIBLE);
            openBt.setText("OPEN");
            saveBt.setVisibility(Component.VISIBLE);
            saveBt.setText("SAVE");
            message.setPaddingLeft(40);
            myHeight = 630;
            cookieBottomComponent.setWidth(screenX);
            cookieBottomComponent.setMarginLeft(20);
            cookieBottomComponent.setMarginRight(20);
            directionalLayout.setPaddingTop(100);
            float[] radius = {70f, 70f, 70f, 70f, 0f, 0f, 0f, 0f};
            element.setCornerRadiiArray(radius); // 设置背景圆角
        } else {
            blank_1.setVisibility(Component.HIDE);
            blank_2.setVisibility(Component.HIDE);
            blank_3.setVisibility(Component.HIDE);
            blank_4.setVisibility(Component.HIDE);
            blank_5.setVisibility(Component.HIDE);
            NewBt.setVisibility(Component.HIDE);
            openBt.setVisibility(Component.HIDE);
            saveBt.setVisibility(Component.HIDE);
            message.setPaddingLeft(0);
            myHeight = 288;
            bool = false;
            cookieBottomComponent.setWidth(screenX);
            cookieBottomComponent.setMarginLeft(0);
            cookieBottomComponent.setMarginRight(0);
            float[] radius = {0, 0, 0, 0, 0f, 0f, 0f, 0f};
            element.setCornerRadiiArray(radius); // 设置背景直角
            directionalLayout.setPaddingTop(50);
        }
    }

    private void startAnimationTop() {
        screenY = DisplayManager.getInstance().getDefaultDisplay(myContext).get().getAttributes().height;
        myComponent.setTranslation(0, screenY);
        myComponent.setAlpha(1f);
        settingAnimatorProperty();
        AnimatorProperty animatorProperty = myComponent.createAnimatorProperty()
                .moveFromY(screenY)
                .moveToY(screenY - myHeight)
                .setDuration(500)
                .setCurveType(Animator.CurveType.OVERSHOOT);
        animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                myComponent.setVisibility(Component.VISIBLE);
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                isExit = true;
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        animatorProperty.start();
    }

    private void settingAnimatorProperty () {
        // setting图标旋转
        if (action.getText().contains("SETTINGS")) {
            image.setAlpha(0);
            settingAnimatorProperty = image.createAnimatorProperty()
                    .alpha(1f)
                    .setCurveType(Animator.CurveType.CUBIC_BEZIER_DECELERATION)
                    .setDuration(1000)
                    .rotate(360);
            settingAnimatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    image.setRotation(0);
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });
            settingAnimatorProperty.start();
        }
    }

    /**
     * start Animation Bottom
     */
    public void startAnimationBottom() {
        screenY = DisplayManager.getInstance().getDefaultDisplay(myContext).get().getAttributes().height;
        AnimatorProperty animatorProperty = myComponent.createAnimatorProperty()
                .moveFromY(screenY - myHeight)
                .moveToY(screenY + 200)
                .setDuration(500)
                .setCurveType(Animator.CurveType.ANTICIPATE);
        animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                myComponent.setVisibility(Component.VISIBLE);
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                // 是否需要再次弹出
                if (isNeedTopToBottom) {
                    setStyle();
                    startAnimationTop();
                    isExit = true;
                } else {
                    isExit = false;
                }
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        animatorProperty.start();
    }

    /**
     * start Animation Bottom To Top
     */
    public void startAnimationBottomToTop() {
        // 复原收回后是否还需弹出
        isNeedTopToBottom = true;
        if (isExit) {
            startAnimationBottom();
        } else {
            setStyle();
            startAnimationTop();
        }
        // 不需要缩回，所以不发送事件
        if (!bool) {
            sendHandler();
        } else {
            if (runner != null && myHandler != null) {
                // 取消掉上一次发送的事件
                myHandler.removeAllEvent();
            }
        }
    }

    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            if (eventId == EVENT_MESSAGE_GREEN) {
                Object object = event.object;
                if (object instanceof EventRunner) {
                    // 将原先线程的EventRunner实例投递给新创建的线程
                    EventRunner runner2 = (EventRunner) object;
                    // 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定
                    EventHandler myHandler2 = new EventHandler(runner2) {
                        @Override
                        public void processEvent(InnerEvent event) {
                            isNeedTopToBottom = false;
                            startAnimationBottom();
                        }
                    };
                    int eventId2 = 2;
                    long param2 = 0L;
                    InnerEvent event2 = InnerEvent.get(eventId2, param2, null);
                    myHandler2.sendEvent(event2); // 投递事件到原先的线程
                }
            }
        }
    }

    private void sendHandler() {
        if (runner != null && myHandler != null) {
            // 取消掉上一次发送的事件
            myHandler.removeAllEvent();
        } else {
            runner = EventRunner.create(true); // create()的参数是true时，则为托管模式
            myHandler = new MyEventHandler(runner);
        }
        long param = 0L;
        event = InnerEvent.get(EVENT_MESSAGE_GREEN, param, EventRunner.current());
        myHandler.removeAllEvent();
        myHandler.sendEvent(event, duration);
    }

    /**
     * remove Handler
     */
    public void removeHandler() {
        if (runner != null && myHandler != null) {
            // 取消掉上一次发送的事件
            myHandler.removeAllEvent();
        }
    }

    /**
     * start Right By User
     *
     * @param moveFromX move From X
     * @param moveToX   move To X
     */
    public void startRightByUser(Integer moveFromX, Integer moveToX) {
        isExit = false;
        myComponent.setAlpha(0.5f);
        AnimatorProperty animatorProperty = myComponent.createAnimatorProperty()
                .alpha(0f)
                .moveFromX(moveFromX)
                .moveToX(moveToX)
                .setDuration(200)
                .setCurveType(Animator.CurveType.LINEAR);
        animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        animatorProperty.start();
    }

    /**
     * start Restore By User
     *
     * @param moveFromX 从X轴的距离
     * @param moveToX   移动到X轴的距离
     * @param alpha     透明度
     */
    public void startRestoreByUser(float moveFromX, float moveToX, Float alpha) {
        myComponent.setAlpha(alpha);
        AnimatorProperty animatorProperty = myComponent.createAnimatorProperty()
                .moveFromX(moveFromX)
                .moveToX(moveToX)
                .alpha(1f)
                .setDuration(200)
                .setCurveType(Animator.CurveType.LINEAR);
        animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        animatorProperty.start();
    }

    /**
     * getString
     *
     * @param attrSet      attrSet
     * @param name         name
     * @param defaultValue defaultValue
     * @return String
     */
    private String getString(AttrSet attrSet, String name, String defaultValue) {
        String value = defaultValue;
        if (attrSet.getAttr(name) != null && attrSet.getAttr(name).isPresent()) {
            value = attrSet.getAttr(name).get().getStringValue();
        }
        return value;
    }
}
